import cv2
import cvzone
from cvzone.FaceMeshModule import FaceMeshDetector  # 脸部关键点检测方法
import numpy as np  # 用来创建文本框
 
 
#（1）读取视频图像
# filepath = 'D:/deeplearning/video/eyes.mp4'  # 视频文件位置
cap = cv2.VideoCapture(0)  # 参数填0代表电脑自带摄像头
 
#（2）配置
# 脸部检测方法
detector = FaceMeshDetector(maxFaces=1)  # 最多检测一张脸
# 文本框中的内容
textList = ['anukbcxasxxa4525', 
            'xnsailcnau22222', 
            'xbuikuysalbxsalb',
            'cinaxsabkcnaskmc',
            '4861581816158151']
 
#（3）处理视频图像
while True:
 
    # 图像是否读取成功success，读入的帧图像img
    success, img = cap.read()  # 每次读取一帧
    
    # 创建文本图像，一张黑板
    imgText = np.zeros_like(img)  # 创建一个size和img相同的黑色图像
 
    # 检测脸部关键点，返回绘制关键点后的图像img和脸部关键点坐标faces
    img, faces = detector.findFaceMesh(img, draw=False)  # 不绘制关键点
 
    #（4）处理关键点
    if faces:  # 如果检测到了，那就接下去执行
        
        face = faces[0]  # faces是三维列表，我们只需要第一张脸的所有关键点
 
        pointLeft = tuple(face[145])  # 左眼关键点坐标
        pointRight = tuple(face[374]) # 右眼坐标
        
        # 计算两点之间的线段距离w，相当于勾股定理求距离
        w, _ = detector.findDistance(pointRight, pointLeft)  # 返回线段距离和线段信息(两端点和中点的坐标)
        W = 6.3  # 人脸两眼之间的实际平均距离是6.3cm
        f = 700  # 上一节的代码求焦距，估计一个平均值，作为当前的焦距
 
        # 计算人脸距离屏幕的距离
        d = (W*f)/w
        print('distance face to screen:', d)
 
        # 将距离显示在屏幕上，face[10]代表额头的坐标点，scale矩形框大小，thickness文字大小
        cvzone.putTextRect(img, f'distace:{int(d)}cm', (face[10][0]-100,face[10][1]),
                           scale=2, thickness=3, colorR=(255,255,0), colorT=(0,0,0))
 
        #（4）编写文本
        for i, text in enumerate(textList):
 
            singleHeight = 50 + int(d/2)  # 动态调整文本每行之间的距离
            
            scale = 1 + int(d/20)  # 根据脸和摄像机之间的距离调整字体大小
 
            # 控制每条文本之间的行间距i*singleHeight，scale动态改变字体大小
            cv2.putText(imgText, text, (50,100+i*singleHeight), 
                        cv2.FONT_ITALIC, scale, (255,255,255), 2)
 
    #（5）图像展示
    img = cv2.resize(img, (800,450))
    imgText = cv2.resize(imgText, (800,450))
 
    # 将两张图像组合在一起，排2列，组合后size不变
    imgStacked = cvzone.stackImages([img, imgText], cols=2, scale=1)
 
    cv2.imshow('imgStacked', imgStacked)
    k = cv2.waitKey(20)  # 每帧延迟1毫秒后消失
    if k & 0xFF == 27:  # 键盘上的ESC键退出循环
        break
 
# 释放视频资源
cap.release()
cv2.destroyAllWindows()